<?php
/**
 * Created by PhpStorm.
 * User: Anthony Qu
 * Date: 2017/1/27
 * Time: 下午11:10
 */

namespace App\Traits;

/**
 * 树状态结构格式化处理协助
 * Class TreeFormatTrait
 * @package App\Traits
 */
// todo... 添加yield，和Collection支持
trait TreeFormat
{
    protected $categoryIdName = 'id';

    protected $categoryPidName = 'parent_id';

    protected $treeLevelName = 'level';

    protected $treeHasChildName = 'has_child';

    protected $treeDataLists = [];

    protected $parentListIds = [];


    public function getTopParentData(array $arr, $id = 0)
    {
        $res = null;

        if (!empty($arr)) {
            foreach ($arr as $item) {
                if (0 == $id) {
                    $res = $item;
                    break;
                }

                if ($id == $item[$this->categoryIdName]) {
                    return $this->getTopParentData($arr, $item[$this->categoryPidName]);
                }
            }
        }

        return $res;
    }
    /**
     * 带child子节点的树状结构格式化(尝试加yield试试)
     * @param array $arr
     * @param int $pid
     * @return array
     */
    public function treeSortMultiLevelFormat(array $arr, $pid = 0)
    {
        $lists  = [];

        foreach ($arr as $item) {
            if ($item[$this->categoryPidName] == $pid) {
                $child = $this->treeSortMultiLevelFormat($arr, $item[$this->categoryIdName]);
                $item['child'] = $child;
                $lists[] = $item;
            }
        }

        return $lists;
    }

    /**
     * 无限极分类格式化。(尝试加yield试试)
     *
     * @param array $lists
     * @param int $pid
     * @param int $level
     * @return array
     */
    public function treeSortFormat(array $lists, $pid = 0, $level = 0)
    {
        $this->treeDataLists = [];

        if (empty($lists)) {
            return $lists;
        }

        return $this->treeSort($lists, $pid, $level);
    }

    public function setHasChildField(array $list)
    {
//        foreach () {
//
//        }
    }

    /**
     * 根据父级id，获取所有子级id集合
     * @param array $lists
     * @param $parentId
     * @param bool $isContainsOwn
     * @return array
     */
    public function  getChildIdsByParentId(array $lists, $parentId, $isContainsOwn = false)
    {
        $arr = $this->getChildIds($lists, $parentId);

        if ($isContainsOwn) {
            $arr[] = $parentId;
        }

        return $arr;
    }

    /**
     * 根据子节点id，获取所有它的父级id集合
     * @param array $lists
     * @param $childId
     * @param bool $isContainsOwn
     * @return array
     */
    public function getParentIdsByChildId(array $lists, $childId, $isContainsOwn = false)
    {
        $this->parentListIds = [];
        $parentIds = $this->getParentIds($lists, $childId);

        if ($isContainsOwn) {
            $parentIds[] = $childId;
        }

        return $parentIds;
    }

    /**
     * 从数据中移除自身和自身的子集。
     * @param array $lists
     * @param $ownId
     * @return array
     */
    public function getOutsideOfThisSeries(array $lists, $ownId)
    {
        $ownListIds = $this->getChildIdsByParentId($lists, $ownId, true);
        $list = $this->treeSortFormat($lists);
        $retArr = [];

        if (!empty($ownListIds) && !empty($list)) {
            $retArr = $list;

            foreach ($list as $key => $item) {
                if (in_array($item['id'], $ownListIds)) {
                    unset($retArr[$key]);
                }
            }
        }

        return $retArr;
    }


    /**
     * 设置分类id名称
     * @param $name
     */
    public function setCategoryIdName($name)
    {
        $this->categoryIdName = $name;
    }

    /**
     * 设置分类父级id名称
     * @param $name
     */
    public function setCategoryPidName($name)
    {
        $this->categoryPidName = $name;
    }

    /**
     * 设置树型结构格式化时的level等级名称
     * @param $name
     */
    public function setTreeLevelName($name)
    {
        $this->treeLevelName = $name;
    }

    /**
     * 无限极分类格式化具体操作
     * @param array $lists 所有分类列表
     * @param int $pid 分类的父id
     * @param int $level 分类的层级
     * @return array
     */
    protected function treeSort(array $lists, $pid = 0, $level = 0)
    {
        foreach ($lists as $item) {
            if ($item[$this->categoryPidName] == $pid) {
                $item[$this->treeLevelName] = $level;
                $item[$this->treeHasChildName] = false;
                $dataCount = count($this->treeDataLists);

                // 如果有上级元素，则把上级元素标记为有子节点
                if ($level > 0 && $dataCount > 0) {
                    if ($this->treeDataLists[$dataCount - 1][$this->treeLevelName] < $level) {
                        $this->treeDataLists[$dataCount - 1][$this->treeHasChildName] = true;
                    }
                }

                $this->treeDataLists[] = $item;
                $this->treeSort($lists, $item[$this->categoryIdName], $level + 1);
            }
        }

        return $this->treeDataLists;
    }

    /**
     * 获取父级id具体操作
     * @param $lists
     * @param $childId
     * @return array
     */
    protected function getParentIds($lists, $childId)
    {
        foreach ($lists as $item) {
            if ($item[$this->categoryIdName] == $childId && $item[$this->categoryPidName] > 0) {
                $this->parentListIds[] = $item[$this->categoryPidName];
                $this->getParentIds($lists, $item[$this->categoryPidName]);
            }
        }

        return $this->parentListIds;
    }

    /**
     * 获取子集id具体操作
     * @param $lists
     * @param $parentId
     * @return array
     */
    protected function getChildIds($lists, $parentId)
    {
        $arr = [];

        $subLists = $this->treeSortFormat($lists, $parentId);

        foreach ($subLists as $item) {
            $arr[] = $item[$this->categoryIdName];
        }

        return $arr;
    }
}